# -*- coding:utf-8 -*-
import time

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from src.com.bsjs.util.base_util import BaserUtil


class SeleniumClient():
    def __init__(self, driver=None, headless_flag=False, load_selenium=False, mobile_flag=False):
        if load_selenium == True:
            if driver == None:
                driver = self.get_defaule_driver(headless_flag, mobile_flag)
            self.driver = driver
            self.com_client = BaserUtil()

    def get_defaule_driver(self, headless_flag, mobile_flag):
        chrome_options = Options()
        if headless_flag:
            chrome_options.add_argument("--headless")
        if mobile_flag:
            # 设置浏览器窗口大小为手机分辨率
            mobile_emulation = {
                "deviceMetrics": {"width": 375, "height": 812, "pixelRatio": 3.0},
                "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"
            }
            chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
        chrome_options.add_argument(
            "User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36")
        driver = webdriver.Chrome(options=chrome_options)
        driver.maximize_window()
        return driver

    def open_url(self, URL, driver=None, fast_falg=False):
        if driver == None:
            driver = self.driver
        driver.get(URL)
        # # 等待body加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def clink(self, element, driver=None, fast_falg=False, view_falg=True):
        if driver == None:
            driver = self.driver
        if view_falg:
            # 将逛遍移动到可视区域
            driver.execute_script("arguments[0].scrollIntoView(true);", element)
        element.click()
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def move(self, element, driver=None, fast_falg=False, view_falg=True):
        if driver == None:
            driver = self.driver
        if view_falg:
            # 将逛遍移动到可视区域
            driver.execute_script("arguments[0].scrollIntoView(true);", element)
            # 创建ActionChains对象
        actions = ActionChains(driver)
        # 将光标移动到元素上
        actions.move_to_element(element)
        # 执行所有的操作
        actions.perform()
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def move_and_clink(self, element, driver=None, fast_falg=False, view_falg=True):
        if driver == None:
            driver = self.driver
        if view_falg:
            # 将逛遍移动到可视区域
            driver.execute_script("arguments[0].scrollIntoView(true);", element)
        # 创建ActionChains对象
        actions = ActionChains(driver)
        # 将光标移动到元素上
        actions.move_to_element(element)
        # 执行点击动作
        actions.click()
        # 执行所有的操作
        actions.perform()
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)

        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def move_and_clink_center(self, element, driver=None, fast_falg=False, view_falg=True):
        if driver == None:
            driver = self.driver
        if view_falg:
            # 将逛遍移动到可视区域
            driver.execute_script("arguments[0].scrollIntoView(true);", element)
        # 创建ActionChains对象
        # 获取input元素的宽度和高度
        width = element.size['width']
        height = element.size['height']
        # 计算input元素中心位置的偏移量
        offset_x = width / 2
        offset_y = height / 2

        # 将鼠标移动到input元素的中心位置
        actions = ActionChains(driver)
        actions.move_to_element_with_offset(element, offset_x, offset_y)
        self.com_client.sleep(0.5)
        # 执行点击动作
        actions.click()
        # 执行所有的操作
        actions.perform()
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def move_and_clink_xpath(self, xpath, driver=None, fast_falg=False, index=0):
        if driver == None:
            driver = self.driver
        element = driver.find_elements(By.XPATH, xpath)[index]
        return self.move_and_clink(element=element, driver=driver, fast_falg=fast_falg)

    def find_element(self, xpath, driver=None, index=0):
        elements = self.find_elements(xpath=xpath, driver=driver)
        if elements == None or len(elements) == 0:
            return
        return elements[index]

    def find_elements(self, xpath, driver=None):
        if driver == None:
            driver = self.driver
        elements = driver.find_elements(By.XPATH, xpath)
        return elements

    """
    <select id="rateyear">
        <option value="2023">
            2023年
        </option>
        <option value="2022">
            2022年
        </option>
    </select>

    xpath="//select//option, xpath设置值应该到这里,仅仅适用select元素
    """

    def select_element_xpath(self, xpath, driver=None, fast_falg=False, index=0):
        select_box = self.find_element(xpath=xpath, driver=driver, index=index)
        select = Select(select_box)
        select.select_by_index(index)
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def switch_frame_xpath(self, xpath, driver=None, fast_falg=False, index=0):
        if driver == None:
            driver = self.driver
        iframe = self.find_element(xpath=xpath, driver=driver, index=index)
        return self.switch_frame(iframe=iframe, driver=driver, fast_falg=fast_falg)

    def switch_frame(self, iframe, driver=None, fast_falg=False):
        if driver == None:
            driver = self.driver
        driver.switch_to.frame(iframe)
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def source_code(self, driver=None, fast_falg=True):
        if driver == None:
            driver = self.driver
        # 等待body加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.3)
        driver_page_source = driver.page_source
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver_page_source

    def current_url(self, driver=None, fast_falg=False):
        if driver == None:
            driver = self.driver
        # 等待body加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        current_url = driver.current_url
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return current_url

    def close_other_window(self, driver=None, unexp_index=0):
        if driver == None:
            driver = self.driver
        # 等待body加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        handles = driver.window_handles
        if len(handles) == 1:
            return driver
        for index, handle in enumerate(handles):
            if unexp_index == index:
                continue
            driver.switch_to.window(driver.window_handles[-1])
            wait = WebDriverWait(driver, 10)
            wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
            self.com_client.sleep(0.1)
            driver.close()
            if index == len(handles) - 1:
                driver.switch_to.window(driver.window_handles[0])
                wait = WebDriverWait(driver, 10)
                wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
                self.com_client.sleep(0.1)

    def scollp_2top(self, driver=None, fast_falg=False):
        if driver == None:
            driver = self.driver
        # 使用JavaScript滑动滚动条到顶部
        driver.execute_script("window.scrollTo(0, 0);")
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)

    def scollp_down(self, driver=None, scroll_distance=0, fast_falg=False):
        if driver == None:
            driver = self.driver
        # 使用JavaScript滑动滚动条到顶部
        if scroll_distance <= 0:
            return
        # 获取页面的body元素
        body = driver.find_element(By.TAG_NAME, "body")
        actions = ActionChains(driver)
        actions.move_to_element(body).click_and_hold().move_by_offset(0, scroll_distance).release().perform()
        # 等待body加载完成
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        current_url = driver.current_url
        if not fast_falg:
            self.com_client.sleep_period_time(min_value=3, max_value=6)
        return driver

    def get_screen_height(self, driver=None, scroll_distance=0, fast_falg=False):
        if driver == None:
            driver = self.driver
        # 获取屏幕高度
        screen_height = driver.execute_script("return window.innerHeight")
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.1)
        return screen_height

    # 获取有几个窗口
    def win_num(self, driver=None):
        if driver == None:
            driver = self.driver
        return len(driver.window_handles)

    def swithch_new(self, driver=None):
        if driver == None:
            driver = self.driver
        driver.switch_to.window(driver.window_handles[-1])
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        return driver

    def close_and_swithch(self, driver=None):
        win_num = self.win_num()
        if win_num == 1:
            return
        if driver == None:
            driver = self.driver
        driver.close()
        driver.switch_to.window(driver.window_handles[0])
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.TAG_NAME, "body")))
        self.com_client.sleep(0.5)
        return driver
